<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=0.5" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>WXInlinePlayer demo</title>
    <style>
      html,
      td,
      th,
      body {
        font-size: 12px;
        text-align: center;
        background-color: #eee;
      }

      #wrapper {
        width: 100%;
        top: 50px;
        text-align: center;
        margin: auto;
      }

      #wrapper #header {
        margin: auto;
        text-align: left;
        margin-bottom: 10px;
        padding-top: 30px;
      }

      #wrapper input[type="number"] {
        width: 40px;
        height: 26px;
        padding: 0;
        margin: 0;
        border: 1px solid #666;
        text-align: center;
      }

      #wrapper button {
        width: 80px;
        height: 28px;
        border: 1px solid #666;
        background-color: #fff;
        font-size: 14px;
      }

      #canvas {
        width: 800px;
        height: 400px;
        margin: auto;
        background-color: #333;
      }

      #resetBtn {
        /* visibility: hidden; */
        background-color: orange !important;
      }

      #footer {
        margin: 10px auto;
      }
      #footer > span {
        display: inline-table;
        color: gray;
        min-width: 15%;
      }
    </style>
  </head>

  <body>
    <div id="wrapper">
      <div id="header">
        <input
          type="text"
          id="iUrl"
          value=""
          style="width: 786px; height: 10px; margin: 0; padding: 5px; margin-bottom: 5px; display: block;"
        />
        <input type="number" id="iChunkSize" value="128" />
        chunkSize&nbsp;&nbsp;&nbsp;
        <input type="number" id="iBuffer" value="500" />
        bufferingTime&nbsp;&nbsp;&nbsp;
        <input type="number" id="iPreload" value="500" />
        preloadTime&nbsp;&nbsp;&nbsp;
        <div style="margin-right: 1000px; margin-bottom: 5px;"></div>
        <input type="checkbox" id="iH265" /><label for="iH265">isH265</label>
        <input type="checkbox" id="iIsLive" checked/><label for="iIsLive">isLive</label>
        <input type="checkbox" id="iHasAudio" checked /><label for="iHasAudio">hasAudio</label>
        <input type="checkbox" id="iHasVideo" checked /><label for="iHasVideo">hasVideo</label>
        <input type="checkbox" id="iLoop" checked /><label for="iLoop">loop</label>
        <input type="checkbox" id="iAutoPlay" checked /><label for="iAutoPlay">autoplay</label>
        <button id="resetBtn">重设</button>
      </div>
      <canvas id="canvas"></canvas>
      <div id="footer">
        <span id="status">状态：待播放</span>
        <span id="duration">
          可播放时长: 0s
        </span>
        <span id="time">
          进度：0s
        </span>
        <span id="performance">
          解码平均：0ms, 单元平均：0ms
        </span>
      </div>
      <button id="playBtn">播放</button>
      <button id="stopBtn">停止</button>
      <button id="pauseBtn">暂停</button>
      <button id="resumeBtn">恢复</button>
      <button id="muteBtn">静音切换</button>

      <input type="number" name="volume" step="0.1" max="1.0" min="0.0" value="1.0" />
      <span>音量设置</span>
    </div>
    <script src="./index.js"></script>
    <script>
      (() => {
        const $ = document.getElementById.bind(document);
        const $canvas = $("canvas");
        const $status = $("status");
        const $time = $("time");
        const $duration = $("duration");
        const $performance = $("performance");

        const defautVideoUrl = "https://ks3-cn-beijing.ksyun.com/ksplayer/h265/outside_demo/v1.1.3/720P2M30fpsh265-wasmtest.flv";
        const videoHeight = 400;
        const videoWidth = 800;

        let player = null;

        //////////////main logic///////////////////////////////////////////////////////

        (function () {
          //default setting
          $("header").style.width = videoWidth + "px";
          $("footer").style.width = videoWidth + "px";
          $("iUrl").value = defautVideoUrl;
          $("iH265").checked = true;

          //set UI
          setUI();

          //set events
          $canvas.onclick = () => {
            $canvas.requestFullscreen();
          };

          $("iIsLive").addEventListener("change", () => {
            setUI();
          });
        })();

        ///////////////////////////////////////////////////////////////////////////////

        function getOptions() {
          return {
            url: $("iUrl").value,
            $container: $canvas,
            hasVideo: $("iHasVideo").checked,
            hasAudio: $("iHasAudio").checked,
            volume: 1.0,
            muted: false,
            autoplay: $("iAutoPlay").checked,
            loop: $("iLoop").checked,
            isLive: $("iIsLive").checked,
            chunkSize: parseInt($("iChunkSize").value) * 1024,
            preloadTime: parseInt($("iPreload").value),
            bufferingTime: parseInt($("iBuffer").value),
            cacheSegmentCount: 64,
            customLoader: null,
          };
        }

        function initPlayer(options) {
          let isH265 = $("iH265").checked;
          WXInlinePlayer.init({
            asmUrl: "./prod." + (isH265 ? "h265" : "all") + ".asm.combine.js",
            wasmUrl: "./prod." + (isH265 ? "h265" : "all") + ".wasm.combine.js",
          })
          
          return WXInlinePlayer.ready().then(()=>{
            player = new WXInlinePlayer(getOptions());
            player.on("loadError", (e) => {
              console.e("loadError", e);
            });
            player.on("loadSuccess", () => {
              console.log("loadSuccess");
            });
            player.on("mediaInfo", (mediaInfo) => {
              console.log("mediaInfo", mediaInfo);
              const { onMetaData } = mediaInfo;
              //注意：这里是指定绘制的真实分辨率。若要让canvas拉伸填满指定的高宽，则由css的style.width和style.height决定。
              $canvas.height = onMetaData.height || videoHeight;
              $canvas.width = onMetaData.width || videoWidth;
              for (let i = 0; i < onMetaData.length; i++) {
                if ("height" in onMetaData[i]) {
                  $canvas.height = onMetaData[i].height;
                } else if ("width" in onMetaData[i]) {
                  $canvas.width = onMetaData[i].width;
                }
              }
            });

            player.on("play", () => {
              $status.innerHTML = "状态: 开播了";
            });
            player.on("buffering", () => {
              $status.innerHTML = "状态: 加载中";
            });
            player.on("playing", () => {
              $status.innerHTML = "状态: 播放中";
            });
            player.on("paused", () => {
              $status.innerHTML = "状态：已暂停";
            });
            player.on("stopped", () => {
              $status.innerHTML = "状态：已停止";
            });
            player.on("end", () => {
              $status.innerHTML = "状态：已放完";
            });
            player.on("timeUpdate", (timestamp) => {
              $time.innerHTML = "进度：" + Math.ceil((100 * timestamp) / player.getDuration()) + "%";
              $duration.innerHTML = "可播放时长: " + Math.ceil(player.getAvaiableDuration() / 1000) + "s";
            });
            player.on("performance", ({ averageDecodeCost, averageUnitDuration }) => {
              $performance.innerHTML =
                "解码平均：" +
                Math.floor(averageDecodeCost) +
                "ms, 单元平均：" +
                Math.floor(averageUnitDuration) +
                "ms";
            });
          });
        }

        function setUI() {
          let chked = !$("iIsLive").checked;
          let isShow = chked ? "inline" : "none";
          $("pauseBtn").style.display = isShow;
          $("resumeBtn").style.display = isShow;
        }

        //addEventListener()添加的匿名函数无法通过removeEventListener()移除,会造成内存泄漏
        //所以要对每个事件处理函数命名

        let fnPlay = () => {
          initPlayer(getOptions()).then(() => {
            $("resetBtn").style.visibility = "visible";
            player.play();
          });
        };
        $("playBtn").addEventListener("click", fnPlay);

        let fnPause = () => player.pause();
        $("pauseBtn").addEventListener("click", fnPause);

        let fnResume = () => player.resume();
        $("resumeBtn").addEventListener("click", fnResume);

        let fnMute = () => player.mute(!player.mute());
        $("muteBtn").addEventListener("click", fnMute);

        let fnChange = (ev) => player.volume(ev.target.value);
        document.querySelector("input[name=volume]").addEventListener("change", fnChange);

        let fnStop = () => player.stop();
        $("stopBtn").addEventListener("click", fnStop);

        let fnReset = () => {
          if (player) {
            player.stop();
            player = null;
          }

          //you must remove all eventListeners to prevent from memory leaking
          $("playBtn").removeEventListener("click", fnPlay);
          $("pauseBtn").removeEventListener("click", fnPause);
          $("resumeBtn").removeEventListener("click", fnResume);
          $("muteBtn").removeEventListener("click", fnMute);
          document.querySelector("input[name=volume]").removeEventListener("click", fnChange);
          $("stopBtn").removeEventListener("click", fnStop);
          $("resetBtn").removeEventListener("click", fnReset);
          //reload player
          initPlayer(getOptions());
        };
        $("resetBtn").addEventListener("click", fnReset);
      })();
    </script>
  </body>
</html>
